package com.mew.chess.core.game.yxx.game.task;

import com.mew.chess.core.common.handler.ChessPushMessageUtil;
import com.mew.chess.core.common.message.response.ChipMessage;
import com.mew.chess.core.common.provide.GameFeignService;
import com.mew.chess.core.common.utils.ChessGameUtil;
import com.mew.chess.core.game.yxx.game.YxxGameManager;
import com.mew.chess.core.game.yxx.game.YxxRoomManager;
import com.mew.chess.core.game.yxx.game.common.YxxBetType;
import com.mew.chess.core.game.yxx.game.common.YxxConstantValue;
import com.mew.chess.core.game.yxx.game.common.YxxLinkType;
import com.mew.chess.core.game.yxx.game.core.YxxGame;
import com.mew.chess.core.game.yxx.game.message.YxxDealCardMessage;
import com.mew.chess.core.game.yxx.game.message.YxxPushCMDMapType;
import com.mew.chess.core.game.yxx.game.message.YxxPushPaymentMessage;
import com.mew.chess.core.game.yxx.game.message.YxxUserMessage;
import com.mew.common.dc.redis.GameRoomRedisService;
import com.mew.common.enm.UserType;
import com.mew.common.entity.config.Room;
import com.mew.common.rest.game.BetAfterRequest;
import com.zebra.common.concurrent.ZebraExecutorManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
@Slf4j
public class YxxPaymentTask {

    @Autowired
    private GameRoomRedisService gameRoomRedisService;
    @Autowired
    private GameFeignService feignService;

    public void payment(int roomId){
        YxxRoomManager roomManager = YxxGameManager.getInstance().getController(roomId);
        if (!roomManager.getPlayerList().isEmpty()){
            computePayment(roomManager);
            persistenceData(roomManager);
        }

        paymentLinkType(roomManager);
        sendPaymentMsg(roomManager);
    }

    private void paymentLinkType(YxxRoomManager roomManager){
        roomManager.setRuleTime(YxxConstantValue.PAYMENT_TIME);
        roomManager.setLinkType(YxxLinkType.Payment.code());
        roomManager.setStartTime(System.currentTimeMillis());
    }

    private void computePayment(YxxRoomManager roomManager){

        YxxGame yxxGame = roomManager.getDealCardMessage().getYxxGame();
        roomManager.addHistoryVOList(yxxGame.getDice());

        roomManager.getPlayerList().values().stream().collect(Collectors.toList()).forEach(u->doPaymentRecord(yxxGame,u));

    }

    private void doPaymentRecord(YxxGame yxxGame, YxxUserMessage userMessage){

        if (userMessage.getBets().size()>0){
            long bet = 0;
            long paymentNumber = 0;
            for (ChipMessage betmsg : userMessage.getBets()) {
                paymentNumber+= (betmsg.getBetNumber()* yxxGame.payment(YxxBetType.parse(betmsg.getBetType())));
                bet+=betmsg.getBetNumber();
            }
            userMessage.setBetNumber(bet);
            userMessage.setPaymentNumber(paymentNumber);
        }

    }


    private void persistenceData(YxxRoomManager yxxRoomManager){
        //local compute
        Collection<YxxUserMessage> userMessages = yxxRoomManager.getPlayerList().values().stream().filter(u->u.getBets().size()>0).collect(Collectors.toList());
        List<BetAfterRequest> list = new ArrayList<>(userMessages.size());

        Room room = gameRoomRedisService.getRedisRoom(yxxRoomManager.getGameId(), yxxRoomManager.getRoomId());

        userMessages.forEach(v -> {
            //税 桌费
            v.setBetNumber(v.getBetNumber());
            v.setTax(ChessGameUtil.computeTax(v.getPaymentNumber(), 0));
            v.setPaymentNumber(v.getPaymentNumber() - v.getTax());

            BetAfterRequest record = builPlayRecord(yxxRoomManager, v);

            if (UserType.Robot.code()!=v.getUserType()){
                list.add(record);
            }else {
                v.setPlayTimes(1+v.getPlayTimes());
            }

            v.updateGoldNumber(record.getPayment());

        });

        int size = list.size();
        log.debug("---------plyer size {}", size);
        if (size < 30){
            ZebraExecutorManager.getInstance().getDefaultExecutor().execute(() -> {
                feignService.chessBetAfter(list);
            });
            return;
        }


        ZebraExecutorManager.getInstance().getDefaultExecutor().execute(() -> {
            int s = 30;
            int c = (size / s) + 1;
            try {
                for (int i=0; i<c && i*s < size; i++){
                    TimeUnit.MILLISECONDS.sleep(200);
                    List<BetAfterRequest> subList = list.stream().skip(i*s).limit(s).collect(Collectors.toList());
                    feignService.chessBetAfter(subList);
                }
            } catch (InterruptedException e) {
            }
        });

    }

    //TODO
    private BetAfterRequest builPlayRecord(YxxRoomManager yxxRoomManager, YxxUserMessage yxxUserMessage){
        long betNumber = yxxUserMessage.getBetNumber();
        long paymentNumber = yxxUserMessage.getPaymentNumber();

        //yxxUserMessage.setPlayer(0); //TODO 参与游戏 解锁

        YxxDealCardMessage dealCardMessage = yxxRoomManager.getDealCardMessage();

        BetAfterRequest request = BetAfterRequest.builder()
                .uid(yxxUserMessage.getUserId())
                .relateInoutId(yxxUserMessage.getInoutId())
                .gameId(yxxUserMessage.getGameId())
                .roomId(yxxUserMessage.getRoomId())
                .bet(betNumber)
                .payment(paymentNumber)
                //.rollerId(dealCardMessage.getRollerId())
                //.strategyType(dealCardMessage.getControlRoom() > 0 ? StrategyType.ControlRoom.code() : 0)
                .betTimes(paymentNumber < 1 ? 0 : (int) (paymentNumber / betNumber))
                .iconResult(dealCardMessage.yxxGame.dice.toString())
                .roomRecord(1)
                //.betArray(StringUtils.toStrByMap(betMap, '_', ';'))
                //.paymentArray(StringUtils.toStrByMap(paymentMap, '_', ';'))
                .ino(yxxRoomManager.getIno())
                .tax(yxxUserMessage.getTax())
                .build();

        return request;
    }

    private void sendPaymentMsg(YxxRoomManager roomManager){

        roomManager.getOnlineUser().forEach((k, session) -> {

            if (null != session){
                YxxPushPaymentMessage pushPaymentMessage = new YxxPushPaymentMessage();
                pushPaymentMessage.setRemainTime(YxxConstantValue.PAYMENT_TIME);

                pushPaymentMessage.setPaymentMessage(roomManager.getPaymentMessage());
                pushPaymentMessage.setHistoryMessage(roomManager.getHistoryVOList());
                pushPaymentMessage.setBigRList(roomManager.getBigRList());

                YxxUserMessage userMessage = roomManager.getPlayer(k);
                pushPaymentMessage.setPaymentNumber(userMessage.getPaymentNumber());
                pushPaymentMessage.setGoldNumber(userMessage.getGoldNumber());
                ChessPushMessageUtil.pushMessage(session, YxxPushCMDMapType.PaymentMessage.code(), pushPaymentMessage);
            }
        });
    }

}
